module.exports = Encryptor; // cmd

function Encryptor(){} // 构造函数模式+原型模式

Encryptor.prototype.crypto = require('crypto');
Encryptor.prototype.fs = require('fs');

Encryptor.prototype.defaultOptions = {
  algorithm: 'aes-128-ecb' // aes192 256
};

/**
 * [combineOptions description] 配置适配器
 * @param  {[type]} options [description]
 * @return {[type]}         [description]
 */
Encryptor.prototype.combineOptions = function(options) {
  var result = {};
  var defaultOptions = this.defaultOptions;

  for(var key in defaultOptions) {
    result[key] = defaultOptions[key];
  }

  for(var key in options) {
    result[key] = options[key];
  }

  return result;
};

/**
 * [encryptFile description] 加密文件，A -> B
 * @param  {[type]}   inputPath  [description]
 * @param  {[type]}   outputPath [description]
 * @param  {[type]}   key        [description]
 * @param  {[type]}   options    [description]
 * @param  {Function} callback   [description]
 * @return {[type]}              [description]
 */
Encryptor.prototype.encryptFile = function(inputPath, outputPath, key, options, callback) {

  if(typeof options === 'function') {
    callback = options;
    options = {};
  }

  options = this.combineOptions(options);

  var inputStream = this.fs.createReadStream(inputPath);
  var outputStream = this.fs.createWriteStream(outputPath);

  var keyBuf = new Buffer(key);
  var cipher = this.crypto.createCipher(options.algorithm, keyBuf);

  inputStream.on('data', function(data) {
    var buf = new Buffer(cipher.update(data), 'binary');
    outputStream.write(buf);
  });

  inputStream.on('end', function() {
    var buf = new Buffer(cipher.final('binary'), 'binary');
    outputStream.write(buf);
    outputStream.end();
    outputStream.on('close', function() {
      callback();
    });
  });
};

/**
 * [encrypt description] 加密文件，A -> A
 * @param  {[type]}   inputPath  [description]
 * @param  {[type]}   outputPath [description]
 * @param  {[type]}   key        [description]
 * @param  {[type]}   options    [description]
 * @param  {Function} callback   [description]
 * @return {[type]}              [description]
 */
Encryptor.prototype.encrypt = function(inputPath, key, options, callback) {

  if(typeof options === 'function') {
    callback = options;
    options = {};
  }

  var fs = this.fs;

  options = this.combineOptions(options);

  var inputStream = fs.createReadStream(inputPath);
  var outputStream = fs.createWriteStream(inputPath + 'New');

  var keyBuf = new Buffer(key);
  var cipher = this.crypto.createCipher(options.algorithm, keyBuf);

  inputStream.on('data', function(data) {
    var buf = new Buffer(cipher.update(data), 'binary');
    outputStream.write(buf);
  });

  inputStream.on('end', function() {
    var buf = new Buffer(cipher.final('binary'), 'binary');
    console.log('\t正在加密...');
    outputStream.write(buf);
    outputStream.end();
    outputStream.on('close', function() {
      // 删除类型为.*New的文件
      fs.unlink(inputPath, function() {
        fs.rename(inputPath + 'New', inputPath, callback);
      });
      // callback();
    });
  });
};

/**
 * [decryptFile description] 解密文件 A -> B
 * @param  {[type]}   inputPath  [description]
 * @param  {[type]}   outputPath [description]
 * @param  {[type]}   key        [description]
 * @param  {[type]}   options    [description]
 * @param  {Function} callback   [description]
 * @return {[type]}              [description]
 */
Encryptor.prototype.decryptFile = function(inputPath, outputPath, key, options, callback) {

  if(typeof options === 'function') {
    callback = options;
    options = {};
  }

  options = this.combineOptions(options);

  var inputStream = this.fs.createReadStream(inputPath);
  var outputStream = this.fs.createWriteStream(outputPath);

  var keyBuf = new Buffer(key);
  var cipher = this.crypto.createDecipher(options.algorithm, keyBuf);

  inputStream.on('data', function(data) {
    var buf = new Buffer(cipher.update(data), 'binary'); //
    outputStream.write(buf);
  });

  inputStream.on('end', function() {
    var buf = new Buffer(cipher.final('binary'), 'binary');
    outputStream.write(buf);
    outputStream.end();
    outputStream.on('close', function() {
      callback();
    });
  });
};

/**
 * [decrypt description] 解密文件 A -> A
 * @param  {[type]}   inputPath  [description]
 * @param  {[type]}   outputPath [description]
 * @param  {[type]}   key        [description]
 * @param  {[type]}   options    [description]
 * @param  {Function} callback   [description]
 * @return {[type]}              [description]
 */
Encryptor.prototype.decrypt = function(inputPath, key, options, callback) {

  if(typeof options === 'function') {
    callback = options;
    options = {};
  }

  var fs = this.fs;
  options = this.combineOptions(options);

  var inputStream = fs.createReadStream(inputPath);
  var outputStream = fs.createWriteStream(inputPath + 'New');

  var keyBuf = new Buffer(key);
  var cipher = this.crypto.createDecipher(options.algorithm, keyBuf);

  inputStream.on('data', function(data) {
    var buf = new Buffer(cipher.update(data), 'binary');
    outputStream.write(buf);
  });

  inputStream.on('end', function() {
    var buf = new Buffer(cipher.final('binary'), 'binary');
    console.log('\t正在解密...');
    outputStream.write(buf);
    outputStream.end();
    outputStream.on('close', function() {
      // 删除类型为.*New的文件
      fs.unlink(inputPath, function() {
        fs.rename(inputPath + 'New', inputPath, callback);
      });
      // callback();
    });
  });
};

